import com.softwarecraftsmen.orogeny.BaseDirectory;
import com.softwarecraftsmen.orogeny.BuildScript;
import com.softwarecraftsmen.orogeny.UpperCaseEnvironmentVariableOnWindows;
import com.softwarecraftsmen.orogeny.buildEnvironments.BuildDateTime;
import static com.softwarecraftsmen.orogeny.actions.DeleteDirectoryAction.deleteDirectory;
import static com.softwarecraftsmen.orogeny.actions.EchoAction.echo;
import static com.softwarecraftsmen.orogeny.actions.EchoAction.echoProperties;
import static com.softwarecraftsmen.orogeny.actions.ExecuteAction.FifteenSeconds;
import static com.softwarecraftsmen.orogeny.actions.ExecuteAction.execute;
import static com.softwarecraftsmen.orogeny.actions.MakeDirectoryAction.makeDirectory;
import static com.softwarecraftsmen.orogeny.actions.RecreateDirectoryAction.recreateDirectory;
import static com.softwarecraftsmen.orogeny.actions.execute.OperatingSystemAndPathDependentExecutable.operatingSystemAndPathDependentExecutable;
import static com.softwarecraftsmen.orogeny.filing.AbsoluteDirectoriesAndFiles.absoluteDirectoriesAndFiles;
import com.softwarecraftsmen.orogeny.filing.AbsoluteDirectory;
import com.softwarecraftsmen.orogeny.filing.AbsoluteFile;
import com.softwarecraftsmen.orogeny.filing.AbsolutePaths;
import com.softwarecraftsmen.orogeny.filing.fileSystems.FileSystem;
import com.softwarecraftsmen.orogeny.operatingSystems.OperatingSystem;
import com.softwarecraftsmen.orogeny.operatingSystems.OperatingSystemFamily;
import com.softwarecraftsmen.orogeny.operatingSystems.OperatingSystemPlatform;
import static com.softwarecraftsmen.orogeny.properties.PropertyName.EnvironmentPATH;
import static com.softwarecraftsmen.orogeny.properties.PropertyNamePrefix.dynamic;
import static com.softwarecraftsmen.orogeny.properties.PropertyNamePrefix.system;

import java.util.UUID;

/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */

//TODO: This will fail on Windows systems and vice versa; parsing currently finds the default file system to interpret characters
//
@BaseDirectory("..")
@UpperCaseEnvironmentVariableOnWindows({"PATH", "CLASSPATH"})
public class Demonstration1BuildScript extends BuildScript
{{
	final AbsoluteDirectory output = inBuildDirectory("outputX");
	final AbsoluteDirectory library = inBuildDirectory("library");
	final AbsoluteDirectory source = inBuildDirectory("source");

	final AbsoluteFile annotationsClassPath = library.subDirectory("IntelliJ", "7").file("annotations.jar");

	// Demonstrate defining dynamic properties
	defineProperty("hello world").as("Hello {system:user.name} I am using {environment:PATH}");
	// Properties have a prefix
	defineProperty("dynamic:hello worldX").as("Recursion {hello world}");
	defineProperty("{yes you can have braces around and { or } in names}").as("braces are allowed in names but those names can not be used recursively ");
	defineProperty("using a braced property recursively is impossible").as("braces in name example does not yet work: '{{yes you can have braces in names}}' and escaped braces '{{' and '}}'.");

	// Demonstrate what's available in the BuildEnvironment
	final BuildDateTime buildDateTime = currentBuildDateTime();
	final String buildName = currentBuildName();
	final UUID buildUuid = currentBuildUuid();
	final FileSystem currentFileSystem = currentFileSystem();
	final OperatingSystem currentOperatingSystem = currentOperatingSystem();
	final OperatingSystemFamily currentOperatingSystemFamily = currentOperatingSystemFamily();
	final OperatingSystemPlatform currentOperatingSystemPlatform = currentOperatingSystemPlatform();
	final AbsoluteDirectory currentWorkingDirectory = currentWorkingDirectory();

	// Demonstrate ways of finding a path
	final AbsoluteDirectory demonstrateRelativeToBuildDirectory1 = inBuildDirectory("library");
	final AbsoluteDirectory demonstrateRelativeToBuildDirectory2 = inBuildDirectory("library", "IntelliJ");
	final AbsoluteDirectory demonstrateUsingPaths1 = demonstrateRelativeToBuildDirectory1.subDirectory("IntelliJ");
	final AbsoluteDirectory demonstrateUsingPaths2 = demonstrateRelativeToBuildDirectory1.subDirectory("IntelliJ", "7");

	// Demonstrate ways of finding a file
	final AbsoluteFile demonstrateUsingFiles1 = demonstrateRelativeToBuildDirectory1.subDirectory("IntelliJ", "7").file("annotations.jar");

	// Demonstrate ways of creating class paths
	final AbsolutePaths commandLineClassPath = absoluteDirectoriesAndFiles
	(
		demonstrateUsingFiles1,
		output,
		library.subDirectory("jopt-simple", "2.4.1").file("jopt-simple-2.4.1-SNAPSHOT.jar")
	).and(absoluteDirectoriesAndFiles
	(
		demonstrateRelativeToBuildDirectory2,
		// Duplicates are silently removed
		demonstrateRelativeToBuildDirectory2
	)).and(demonstrateUsingPaths1);

	// Hidden tasks are not listed when asking for information
	task("demonstrate deleteDirectory").isHidden().does
	(
		deleteDirectory(output)
	);

	task("demonstrate makeDirectory").isHidden().dependsOn("demonstrate deleteDirectory").does
	(
		makeDirectory(output)
	);

	task("demonstrate recreateDirectory").isHidden().does
	(
		recreateDirectory(output)
	);

	/*
		Properties are not well utilised
		Command line properties are not yet available
		See PropertyNamePrefix for the possibilities and PropertyName for common properties
	 */
	task("demonstrate properties").isHidden().does
	(
		echo(dynamic.property("hello world")),
		// This is equivalent to dynamic.property("hello world") as dynamic properties do not need to be prefixed [MAY CHANGE]
		echo(property("hello worldX")),
		// This is equivalent to dynamic.property("hello world") as dynamic properties do not need to be prefixed
		echo(property("dynamic:hello worldX")),
		echo(property("system:user.name")),
		// This is equivalent to property("system:user.name")
		echo(system.property("user.name")),
		echo(property("dynamic:{yes you can have braces around and { or } in names}")),
		echo(property("using a braced property recursively is impossible")),
		// Properties prefixed "orogeny:" are annotations applied to the build script
		echo(property("orogeny:BaseDirectory"))
	);

	task("demonstrate defineProperty in task part 1").isHidden().does
	(
		echo(defineProperty("anon").as("{hello world} again!"))
	);

	task("demonstrate defineProperty in task part 2").isHidden().dependsOn("demonstrate defineProperty in task part 1").does
	(
		echo(property("anon"))
	);

	task("demonstrate echo String").isHidden().does
	(
		echo("hello world")
	);

	task("demonstrate echo any Object").isHidden().does
	(
		echo(demonstrateUsingPaths2)
	);

	task("demonstrate echo all properties known").isHidden().does
	(
		echoProperties()
	);

	// Executable example
	task("demonstrate using an executable").does
	(
		// execute also takes an absolute path
		execute(operatingSystemAndPathDependentExecutable("java")).inWorkingDirectory(inBuildDirectory()).forUpTo(FifteenSeconds).
			withArgument("-help").
			withArguments
			(
				"-verbose", "-X"
			).
			// By design, NO inherited properties are passed. Use withInheritedEnvironmentVariables() if you want this behaviour
			withEnvironmentVariable("PATH", EnvironmentPATH)
	);

	task("demonstrate").dependsOn
	(
		"demonstrate makeDirectory",
		"demonstrate recreateDirectory",
		"demonstrate properties",
		"demonstrate defineProperty in task part 2",
		"demonstrate echo String",
		"demonstrate echo any Object",
		"demonstrate echo all properties known",
		"demonstrate using an executable"
	).does(deleteDirectory(output));
}}